package com.youlu.campus.service.data.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.OrderStatisticsQueryV0;
import com.youlu.campus.entity.system.UserDataPermission;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.ActivityStatisticsService;
import com.youlu.campus.service.data.OrderStatisticsService;
import com.youlu.campus.service.system.UserDataPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class OrderStatisticsServiceImpl implements OrderStatisticsService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private UserDataPermissionService userDataPermissionService;

    @Autowired
    private ActivityStatisticsService activityStatisticsService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String ORDER_LOCK = "order:statistics:orderNo:%s";

    @Override
    @Async
    public void incre(String orderNo) {
        log.info(":>>> 开始记录订单统计数据:{}", orderNo);
        try {
            if(StringUtils.isBlank(orderNo)){
                return;
            }
            //添加分布式锁
            String lockKey = String.format(ORDER_LOCK,orderNo);
            Boolean existKey = redisTemplate.opsForValue().setIfAbsent(lockKey, orderNo, 30L, TimeUnit.MINUTES);
            log.info("【活动订单支付统计】orderNo:{},获取锁状态->{}",orderNo, existKey);
            if (Objects.nonNull(existKey) && !existKey) {
                log.error("【活动订单支付统计】频繁请求 orderNo:{}", orderNo);
                return;
            }
            Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
            OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
            if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getActivityId())) {
                log.error(":>>> 订单不存在:{}", orderNo);
                return;
            }
            ActivityInfo activityInfo = activityService.findOne(orderInfo.getActivityId());
            List<OOrderInfo> subs = mongoTemplate.find(query, OOrderInfo.class);
            Integer payNum = 0;
            for (OOrderInfo orderInfo1 : subs) {
                if (!Boolean.TRUE.equals(orderInfo1.getGifted())) {
                    payNum++;
                }
                Integer price = null;
                Integer expressFee = 0;
                if (Objects.nonNull(orderInfo.getExpressFee())) {
                    expressFee = orderInfo.getExpressFee() / subs.size();
                }
                if(Objects.nonNull(orderInfo1.getTotalFee())){
                    price = orderInfo1.getTotalFee() + expressFee;
                }else{
                    price = orderInfo1.getSalePrice() + expressFee;
                }

//                if (Objects.isNull(orderInfo1.getPayPrice())) {
//                    price = orderInfo1.getSalePrice() + expressFee;
//
//                } else {
//                    price = orderInfo1.getPayPrice() + expressFee;
//                }
//                if (Objects.isNull(price)) {
//                    price = orderInfo1.getSalePrice();
//                }
                if (Objects.isNull(price)) {
                    log.info(":>>> 子订单价格为空");
                    continue;
                }
                Query queryS =
                        new Query().addCriteria(Criteria.where("activityId").is(orderInfo.getActivityId()).and("price"
                        ).is(Double.valueOf(orderInfo1.getSalePrice() + "")));
                if (StringUtils.isNotBlank(orderInfo1.getItemTitle())) {
                    queryS.addCriteria(Criteria.where("itemName").is(orderInfo1.getItemTitle()));
                }
                OrderStatistics orderStatistics = mongoTemplate.findOne(queryS, OrderStatistics.class);
                if (Objects.isNull(orderStatistics)) {
                    orderStatistics = new OrderStatistics();
                    orderStatistics.setActivityId(orderInfo.getActivityId());
                    orderStatistics.setNum(orderInfo1.getNum());
                    orderStatistics.setPrice(Double.valueOf(orderInfo1.getSalePrice() + ""));
                    orderStatistics.setGmv(Double.valueOf(price + ""));
                    orderStatistics.setCreatedTime(new Date());
                    orderStatistics.setActivityName(activityInfo == null ? null : activityInfo.getName());
                    orderStatistics.setItemName(orderInfo1.getItemTitle());
                    mongoTemplate.insert(orderStatistics);
                    log.info(":>>> 新增活动:{}, 价格:{},统计", orderInfo.getActivityId(), orderInfo1.getPayPrice());
                } else {
                    Update update = new Update();
                    update.inc("num", orderInfo1.getNum());
                    update.inc("gmv", Double.valueOf(price + ""));
                    update.set("updatedTime", new Date());
                    mongoTemplate.updateFirst(queryS, update, OrderStatistics.class);
                    log.info(":>>> 修改活动:{}, 价格:{},统计", orderInfo.getActivityId(), orderInfo1.getPayPrice());
                }
            }
            ActivityStatistics req = new ActivityStatistics();
            req.setOrderNum(1);
            req.setPayItemNum(orderInfo.getNum());
            int giftItemNum = subs.stream().filter(subOrder -> subOrder.getGifted()).mapToInt(OOrderInfo::getNum).sum();
            req.setGiftItemNum(giftItemNum);
            req.setItemNum(orderInfo.getNum());
            req.setGmv(Double.valueOf(orderInfo.getTotalFee() == null ? 0 : orderInfo.getTotalFee()));
            req.setType(activityInfo.getType());
            activityStatisticsService.increActivityStatistics(orderInfo.getActivityId(), req);
        } catch (Exception e) {
            log.error(":>>> 累计订单数据错误:{}", e);
        }
    }

    @Override
    public List<OrderStatistics> getByActivityId(String activityId, Double ratio) {
        log.info(":>>> 开始获取活动订单分析:{},比例:{}", activityId, ratio);
        if (StringUtils.isBlank(activityId)) {
            log.error(":>>> 活动ID为空");
            throw new BusinessException("活动ID为空");
        }
        Query query = new Query().addCriteria(Criteria.where("activityId").is(activityId));
        List<OrderStatistics> datas = mongoTemplate.find(query, OrderStatistics.class);
        if (CollectionUtils.isEmpty(datas)) {
            return datas;
        }
        Double gmv = 0.0D;
        Integer total = 0;
        for (OrderStatistics orderStatistics : datas) {
            if (ratio.compareTo(1.0D) == -1) {
                log.info(":>>> 缩小比例:");
                gmv = gmv + (orderStatistics.getGmvJia() == null ? orderStatistics.getGmv() :
                        orderStatistics.getGmvJia());
                total = total + (orderStatistics.getNumJia() == null ? orderStatistics.getNum() :
                        orderStatistics.getNumJia());
            } else {
                gmv = gmv + orderStatistics.getGmv();
                total = total + orderStatistics.getNum();
            }

        }
        DecimalFormat df = new DecimalFormat("######0.00");
        for (OrderStatistics orderStatistics : datas) {
            if (ratio.compareTo(1.0D) == -1) {
                log.info(":>>> 缩小比例:");
                orderStatistics.setGmvRatio(df.format((orderStatistics.getGmvJia() == null ?
                        orderStatistics.getGmv() : orderStatistics.getGmvJia()) * 100 / gmv));
                orderStatistics.setNumRatio(df.format(Double.valueOf((orderStatistics.getNumJia() == null ?
                        orderStatistics.getNum() : orderStatistics.getNumJia())) / total * 100));
                orderStatistics.setPrice(orderStatistics.getPrice() / 100);
                orderStatistics.setGmv((orderStatistics.getGmvJia() == null ? orderStatistics.getGmv() :
                        orderStatistics.getGmvJia()) * ratio / 100);
                Double a = (orderStatistics.getNumJia() == null ? orderStatistics.getNum() :
                        orderStatistics.getNumJia()) * ratio;
                orderStatistics.setNum(a.intValue());
            } else {
                orderStatistics.setGmvRatio(df.format(orderStatistics.getGmv() * 100 / gmv));
                orderStatistics.setNumRatio(df.format(Double.valueOf(orderStatistics.getNum()) / total * 100));
                orderStatistics.setPrice(orderStatistics.getPrice() / 100);
                orderStatistics.setGmv(orderStatistics.getGmv() * ratio / 100);
                Double a = orderStatistics.getNum() * ratio;
                orderStatistics.setNum(a.intValue());
                orderStatistics.setRefundGmv(orderStatistics.getRefundGmv() / 100);
                if (Objects.nonNull(orderStatistics.getNum()) && (orderStatistics.getNum().compareTo(0) == 1)) {
                    orderStatistics.setRefundRatio(df.format(Double.valueOf(orderStatistics.getRefundNum()) / orderStatistics.getNum() * 100));
                } else {
                    orderStatistics.setRefundRatio("0%");

                }
            }

        }
        return datas;
    }

    @Override
    public HashMap<String, List<OrderStatistics>> get(OrderStatisticsQueryV0 req1, String userId) {
        log.info(":>>> 开始获取订单统计数据:{},{}", req1.getPageSize(), userId);
        HashMap<String, List<OrderStatistics>> res = new HashMap<>();
        List<String> activityIds = new ArrayList<>();
        if (StringUtils.isNotBlank(req1.getActivityId())) {
            activityIds.add(req1.getActivityId());
        }
        UserDataPermission req = new UserDataPermission();
        req.setUserId(userId);
        List<UserDataPermission> permissions = userDataPermissionService.list(req);
        Query query = new Query();
        query.limit(req1.getPageSize());
        query.with(Sort.by(
                Sort.Order.desc("updatedTime"),
                Sort.Order.desc("createdTime")));
        if (!CollectionUtils.isEmpty(permissions) && org.apache.commons.collections4.CollectionUtils.isNotEmpty(permissions.get(0).getOrdersActivityIds())) {
            activityIds.addAll(permissions.get(0).getOrdersActivityIds());
        }
        if (!CollectionUtils.isEmpty(activityIds)) {
            query.addCriteria(Criteria.where("activityId").in(activityIds));
        }
        List<OrderStatistics> datas = mongoTemplate.find(query, OrderStatistics.class);
        if (CollectionUtils.isEmpty(datas)) {
            log.error(":>>> 订单统计数据为空:{}", JSON.toJSONString(datas));
            return res;
        }
        for (OrderStatistics o : datas) {
            if (CollectionUtils.isEmpty(permissions) || CollectionUtils.isEmpty(permissions.get(0).getOrdersActivityIds())) {
                res.put(o.getActivityName(), this.getByActivityId(o.getActivityId(), 1.0D));
            } else {
                res.put(o.getActivityName(), this.getByActivityId(o.getActivityId(), permissions.get(0).getGmvRatio()));
            }

        }
        return res;
    }

    @Override
    public void updateRefundStatistics(String orderNo, List<OOrderInfo> subOrderInfos) {
        log.info(":>>> 开始更新订单退款统计:{},{}", orderNo, JSON.toJSON(subOrderInfos));
        if (StringUtils.isBlank(orderNo) || CollectionUtils.isEmpty(subOrderInfos)) {
            log.error(":>>> 更新订单退款错误:订单编号或子订单为空");
            return;
        }
        try {
            Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
            OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
            if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getActivityId())) {
                log.error(":>>> 订单不存在:{}", orderNo);
                return;
            }
            ActivityInfo activityInfo = activityService.findOne(orderInfo.getActivityId());
            for (OOrderInfo orderInfo1 : subOrderInfos) {
                Integer price = null;
                Integer expressFee = 0;
                if (Objects.nonNull(orderInfo.getExpressFee())) {
                    expressFee = orderInfo.getExpressFee() / subOrderInfos.size();
                }
                if (Objects.isNull(orderInfo1.getPayPrice())) {
                    price = orderInfo1.getItemPrice() + expressFee;

                } else {
                    price = orderInfo1.getPayPrice() + expressFee;
                }
                if (Objects.isNull(price)) {
                    price = orderInfo1.getSalePrice();
                }
                if (Objects.isNull(price)) {
                    log.info(":>>> 子订单价格为空");
                    continue;
                }
                Query queryS =
                        new Query().addCriteria(Criteria.where("activityId").is(orderInfo.getActivityId()).and("price"
                        ).is(Double.valueOf(price + "")));
                if (StringUtils.isNotBlank(orderInfo1.getItemTitle())) {
                    queryS.addCriteria(Criteria.where("itemName").is(orderInfo1.getItemTitle()));
                }
                OrderStatistics orderStatistics = mongoTemplate.findOne(queryS, OrderStatistics.class);
                if (Objects.isNull(orderStatistics)) {
                    orderStatistics = new OrderStatistics();
                    orderStatistics.setActivityId(orderInfo.getActivityId());
                    orderStatistics.setNum(1);
                    orderStatistics.setPrice(Double.valueOf(price + ""));
                    orderStatistics.setCreatedTime(new Date());
                    orderStatistics.setActivityName(activityInfo == null ? null : activityInfo.getName());
                    orderStatistics.setItemName(orderInfo1.getItemTitle());
                    orderStatistics.setRefundNum(orderInfo1.getNum());
                    orderStatistics.setRefundGmv(Double.valueOf(price + ""));
                    mongoTemplate.insert(orderStatistics);
                    log.info(":>>> 新增活动:{}, 价格:{},统计", orderInfo.getActivityId(), orderInfo1.getPayPrice());
                } else {
                    Update update = new Update();
                    update.inc("refundNum", orderInfo1.getNum());
                    update.inc("refundGmv", Double.valueOf(price + ""));
                    update.set("updatedTime", new Date());
                    mongoTemplate.updateFirst(queryS, update, OrderStatistics.class);
                    log.info(":>>> 修改活动:{}, 价格:{},统计", orderInfo.getActivityId(), orderInfo1.getPayPrice());
                }

            }

        } catch (Exception e) {
            log.error(":>>> 累计订单数据退款错误:{}", e);
        }
    }

    @Override
    public Page<HashMap<String, List<OrderStatistics>>> list(OrderStatisticsQueryV0 req1) {
        log.info(":>>> 开始获取订单统计数据:{}", JSON.toJSONString(req1));
        HashMap<String, List<OrderStatistics>> res = new HashMap<>();
        UserDataPermission req = new UserDataPermission();
        req.setUserId(req1.getUserId());
        List<UserDataPermission> permissions = userDataPermissionService.list(req);
        Query query = new Query();
        if (StringUtils.isNotBlank(req1.getItemId())) {
            query.addCriteria(Criteria.where("itemId").is(req1.getItemId()));
        }
        Long total = mongoTemplate.count(query, OrderStatistics.class);
        query.with(Sort.by(Sort.Direction.DESC, "createdTime"));

        if (!CollectionUtils.isEmpty(permissions) && org.apache.commons.collections4.CollectionUtils.isNotEmpty(permissions.get(0).getOrdersActivityIds())) {
            if (StringUtils.isNotBlank(req1.getActivityId())) {
                permissions.get(0).getOrdersActivityIds().add(req1.getActivityId());
            }
            query.addCriteria(Criteria.where("activityId").in(permissions.get(0).getOrdersActivityIds()));
        } else {
            if (StringUtils.isNotBlank(req1.getActivityId())) {
                query.addCriteria(Criteria.where("activityId").is(req1.getActivityId()));
            }
        }

        PageRequest pageRequest = PageRequest.of(req1.getPage() - 1, req1.getPageSize());
        List<OrderStatistics> datas = mongoTemplate.find(query.with(pageRequest), OrderStatistics.class);
        if (Objects.nonNull(datas)) {
            for (OrderStatistics o : datas) {
                if (CollectionUtils.isEmpty(permissions) || CollectionUtils.isEmpty(permissions.get(0).getOrdersActivityIds())) {
                    res.put(o.getActivityName(), this.getByActivityId(o.getActivityId(), 1.0D));
                } else {
                    res.put(o.getActivityName(), this.getByActivityId(o.getActivityId(),
                            permissions.get(0).getGmvRatio()));
                }

            }
        }
        return null;
//        return PageableExecutionUtils.getPage(res, pageRequest, () -> total);
    }
}

